#!/bin/bash

# Copyright (C) 2022-2025 Free Software Foundation, Inc.

# This file is part of GNU Emacs.

# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# GNU Emacs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

# This script is meant to be used as ./admin/emake, and will compile
# the Emacs tree with virtually all of the informational messages
# removed, and with errors/warnings highlighted in red.  It will also
# run the test files belonging to files that have changed.  It'll give
# a quick overview to confirm that nothing has broken, for instance
# after doing a "git pull".  It's not meant to be used during actual
# development, because it removes so much information that commands
# like `next-error' won't be able to jump to the source code where
# errors are.

# It has a few options:
# with --no-color errors/warnings are not highlighted
# with --no-check test files are not run
# with --no-fast the FAST=true make variable is not set (see Makefile.in)
# with --quieter only errors/warnings remain visible

cores=1

# Determine the number of cores.
if [ -f /proc/cpuinfo ]; then
    cores=$(($(grep -E "^physical id|^cpu cores" /proc/cpuinfo |\
	awk '{ print $4; }' |\
	sed '$!N;s/\n/ /' |\
	uniq |\
	sed 's/^[0-9]*/+/')))
fi

NOCOLOR=0
NOCHECK=0
FASTOPT="FAST=true"
QUIETER=0
while :
do
    [[ "X$1" == "X--no-color" ]] && { NOCOLOR=1; shift; continue; }
    [[ "X$1" == "X--no-check" ]] && { NOCHECK=1; shift; continue; }
    [[ "X$1" == "X--no-fast" ]] && { FASTOPT=""; shift; continue; }
    [[ "X$1" == "X--quieter" ]] && { QUIETER=1; shift; continue; }
    break
done

make $FASTOPT -j$cores "$@" 2>&1 | \
sed -u 's# \.\./\.\./# #
s# \.\./# #
s#^Configuring local git # Configuring local git #
s#^Installing git hooks...# Installing git hooks...#
s#^Running # Running #
s#^Configured for # Configured for #
s#^./temacs.*#  \\& #
s#^make.*Error#  \\& #
s#^Dumping under the name.*#  \\& #
:a;/\\$/N;s/\\\n//;ta
' | \
grep -E --line-buffered -v "^make|\
^Loading|\
SCRAPE|\
INFO.*Scraping.*[.] ?\$|\
INFO.*Scraping.*done\$|\
GEN.*etc/DOC|\
GEN.*autoloads|\
^Waiting for git|\
^Finding pointers|\
^Using load-path|\
^Adding name|\
^Dump mode|\
^Dumping finger|\
^Byte counts|\
^Reloc counts|\
^Pure-hashed|\
^cp -f temacs|\
^rm -f bootstrap|\
^Dump complete|\
^rm -f emacs|\
mkdir -p etc|\
mkdir -p info|\
mkdir -p lisp|\
^LC_ALL.*pdump|\
^cp -f emacs.p|\
GEN.*loaddefs|\
^Reloading stale|\
^Source file.*newer than|\
^Directories for loaddefs|\
^./autogen.sh|\
^[Cc]hecking |\
^.Read INSTALL.REPO for more|\
^Your system has the required tools.|\
^Building aclocal.m4|\
^Building 'aclocal.m4'|\
^ Running 'autoreconf|\
^You can now run './configure'|\
^./configure|\
^configure: creating|\
^\"configure\" file built.|\
^There seems to be no|\
^config.status:|\
ELN_DESTDIR|\
--bin-dest |\
^ *$|\
^Makefile built|\
The GNU allocators don't work|\
^git config |\
^'\.git/|\
^\^\(\(|\
^ANCIENT=yes make|\
^touch -t|\
^'build-aux/git-hooks|\
^GNUmakefile:[0-9]*: There seems to be no |\
^GNUmakefile:[0-9]*: Running |\
^GNUmakefile:[0-9]*: No Makefile|\
^rm -f |\
^rm -rf|\
^find \. |\
^rm -fr deps|\
^if test -f \./\.gdbinit|\
^true|\
^for file in |\
^rmdir|\
^\[ \"\.\" = \"\.\" \]\
" | \
while read
do
    C=""
    E=0
    [ ! -v L ] && L=80
    [[ "X${REPLY:0:1}" != "X " ]] && E=1
    [[ "X${REPLY:0:3}" == "X   " ]] && E=1
    (($NOCOLOR == 0)) && (($E == 1)) && C="\033[1;31m"
    (($NOCOLOR == 0)) && (($E == 1)) && C="\033[1;31m"
    if (($QUIETER == 0))
    then
	(($E == 0)) && printf "%s\n" "$REPLY" || printf "${C}%s\033[0m\n" "$REPLY"
    else
	(($E == 0)) && printf "%-${L}s\r" "$REPLY" || printf "${C}%-${L}s\033[0m\n" "$REPLY"
    fi
    L=${#REPLY}
    (($L < 80)) && L=80
done

# If make failed, exit now with its error code.
((${PIPESTATUS[0]} != 0)) && exit ${PIPESTATUS[0]}

(($NOCHECK == 1)) && exit 0

# Run a "make check" on all test files belonging to files that have
# changed since last time.
make -j$cores check-maybe 2>&1 | \
    sed -n '/contained unexpected results/,$p' | \
    grep -E --line-buffered -v "^make" | \
while read
do
    if (($NOCOLOR == 0))
    then
	printf "\033[1;31m%s\033[0m\n" "$REPLY"
    else
	printf "%s\n" "$REPLY"
    fi
done
